/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tarea.memoriaintermedia;
import java.util.LinkedList;
import java.util.Queue;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import java.util.logging.Logger;

/**
 *
 * @author KAREL
 */
public class Gestor_Memoria_Intermedia {
    
   static final Logger logger=Logger.getLogger("Gestion de buffer");
   
   //bloques de la memoria intermedia, buffer y reservas 
   private PaginaTarea[] buffer; //como un arreglo de bits
   //numero de paginas en total en el buffer
   private int numeropagina;
   //posicion en el buffer de la ultima pagina colocada
   private int PosUltiPagina = -1;
   //cola para el control de sustitucion basada en lru
   private Queue colaLRU;
   
   public Gestor_Memoria_Intermedia(int numeroPaginas) {
        this.numeropagina = numeroPaginas;
        
        //crear el buffer con paginas vacias
        buffer=new PaginaTarea[numeroPaginas];
        //crea una cola FIFO
        colaLRU= new LinkedList<Integer>();
        
    }
    
  // Devuelve una pagina conociendo el numero de paginas
   
    public PaginaTarea recuperarPaginaDelBuffer(int numeroPagina){
        
        //verifcar si la posicion esta ya en buffer
        int posicion=posicionDePaginaEnBuffer(numeroPagina);
        if(posicion >= 0) //la pagina esta en al buffer
        {
            //marcar pagina o bloque como recientemente referenciada
            colaLRU.remove(numeroPagina);//eliminar de su posicion anterior para ponerlo al final de la cola
            colaLRU.add(numeroPagina); ///como indicador de ser el ultimo  usado
            //devolver la pagina del buffer al solicitante
            return buffer[posicion];
        }
        return null;
    }

    public PaginaTarea ponerPaginaEnBuffer(PaginaTarea pagina){
        //si la pagina esta en el buffer
        if(estaPaginaEnBuffer(pagina)){
            return null;
        }//si la pagina esta en el buffer pero con espacio en el buffer
        else if(!bufferLleno()){
            //asignar la nueva pagina el bloque o pagina libre
            PosUltiPagina++;
            buffer[PosUltiPagina]=pagina;
            //actualizar la LRU
            colaLRU.remove(PosUltiPagina);
            colaLRU.add(PosUltiPagina);
            return null;
        }//si la pgina no esta en el buffer , pero sin espacion en la memoria intermedia
        else
        {
            int posicion = PaginaNoClavada();
            if (posicion != -1)
            {
                PaginaTarea paginaDescartada = buffer[posicion];
                // Actualizar la nueva pagina en a posicion de la pagina descartada
                buffer[posicion]=pagina;
               // buffer[posicion].setDatos(pagina);
                // actualizar el mas recientemente usado
                colaLRU.add(pagina.getNroPagina());
                /*if (paginaDescartada.isModified())
                    paginaDescartada.Almacenar();*/
                return paginaDescartada;   
            }
            else {
               System.out.println(" ===============================================================");
                System.out.println("Sin espacio para nuevas paginas, todas son paginas clavadas");
                System.out.println("===============================================================");
                return null;
            }                                 
        }
    }
    //consigue el siguiente indicador de la pagina no clavada
        public int PaginaNoClavada()
    {
        //cola auxiliar para iniciar busqueda de no clavados
        Queue ColaAux= colaLRU;
        int idPagEliminada = (Integer) ColaAux.remove();          
        int pos = posicionDePaginaEnBuffer(idPagEliminada);
        PaginaTarea PagEliminada = buffer[pos];
        if(PagEliminada.isFlag())
        {
            boolean PagEncontrada = false;
            int j = -1;
            while(!PagEncontrada && (ColaAux.size() != 0))
            {
                int Eliminada2 = (Integer) ColaAux.remove();                
                j = posicionDePaginaEnBuffer(Eliminada2);
                PaginaTarea paginaDescartada2 = buffer[j];
                if(!paginaDescartada2.isFlag())
                {
                    PagEncontrada = true;
                }
            }
            if (PagEncontrada){
                return j;
            }
            else
                return -1;                
        }
        else
            return pos;
    }
    
       private int posicionDePaginaEnBuffer(int numeroPagina){
            int posicion = -1;
            for(int i = 0; i < buffer.length; i++) {
                if((buffer[i] != null) && (numeroPagina == buffer[i].getNroPagina())){
                    posicion = i;
                    break;
                }
            }   
        return posicion;
       }
    
        private boolean estaPaginaEnBuffer(PaginaTarea pagina){
            return (posicionDePaginaEnBuffer(pagina.getNroPagina()) != -1);
        }
    
        private boolean bufferLleno(){
            return numeropagina-1==PosUltiPagina;
        }
        
        @Override
        public String toString()
        {
            String resultado="";
            for (int i = 0; i < buffer.length; i++) {
                resultado +="Pagina[" +i+ "]:"+ buffer[i]+"\n";
            }
            return resultado +"\n" + this.colaLRU;
        }
        private void esmodificado(PaginaTarea p){
            if (p.isModifica())
                p.Acumular();
        }
        public static void main(String[] args){
            
            
            //crear el gesto de memoria
            Gestor_Memoria_Intermedia gestorbuffer= new Gestor_Memoria_Intermedia(6);
            //paginas del disco
            System.out.println("Paginas del disco: ");
            PaginaTarea[] paginas = new PaginaTarea[6];
            for (int i = 0; i < paginas.length; i++) {
                if(i<=4){ //llenamos paginas y 5 de ellas estan clavadas
                    PaginaTarea pagina= new PaginaTarea(i, "p"+i);
                    pagina.setFlag(true);
                    paginas[i]=pagina;
                    System.out.println(pagina);
                }
                else{//la unica pagina sin clavar
                    PaginaTarea pagina= new PaginaTarea(i, "p"+i);
                    paginas[i]=pagina;
                    System.out.println(pagina);}
            }
            System.out.println("======================================");
            System.out.println("       contenido del gestor");
            System.out.println("======================================");
            System.out.println(gestorbuffer);
            for (int i = 0; i < paginas.length; i++) {
                gestorbuffer.ponerPaginaEnBuffer(paginas[i]);
            }
            System.out.println("contenido del gestor despues de poner bloques");
            System.out.println(gestorbuffer);
            
            System.out.println("poner una pagina en el buffer :");
            PaginaTarea paginaN= new PaginaTarea(10, "p10");
            PaginaTarea paginaE = gestorbuffer.ponerPaginaEnBuffer(paginaN);
            System.out.println(paginaE);
            System.out.println(gestorbuffer);
            
         
            System.out.println(" ");
            System.out.println("modificamos el valor de la ultima pagina del valor 10 a 'modificado'");
            System.out.println(" ");
             gestorbuffer.buffer[5].setDatos("modificado");
             gestorbuffer.esmodificado(gestorbuffer.buffer[5]);
               
            
            System.out.println("recuperar otra pagina del buffer :");//una q no este en la cola
            PaginaTarea pagina2= gestorbuffer.recuperarPaginaDelBuffer(3);
            System.out.println(pagina2);
            System.out.println(gestorbuffer);
            
            
              System.out.println("configuramos la ultima pagina como clavada");
              gestorbuffer.buffer[5].setFlag(true);
             System.out.println("poner una pagina en el buffer :");
            PaginaTarea pag1= new PaginaTarea(11, "p11");
            pag1.setFlag(true);
            PaginaTarea pag2 = gestorbuffer.ponerPaginaEnBuffer(pag1);
            System.out.println(pag2);
            System.out.println(gestorbuffer);
            
            
             
        }
    
    
}
